package top.codedance.iotp.tools.terminal.ui;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import top.codedance.iotp.common.util.HexUtil;
import top.codedance.iotp.common.util.SystemUtil;
import top.codedance.iotp.common.util.VersionFileUtil;
import top.codedance.iotp.iot.sdk.StandandService;
import top.codedance.iotp.iot.sdk.po.sync.ComClientParam;
import top.codedance.iotp.iot.sdk.po.sync.ExecComParam;
import top.codedance.iotp.iot.sdk.po.sync.ExecSystemParam;
import top.codedance.iotp.iot.sdk.po.sync.PowershellSubParam;
import top.codedance.iotp.tools.serverTool.ServerToolApplication;
import top.codedance.iotp.tools.serverTool.ui.Hex2AsciiFrame;
import top.codedance.iotp.tools.terminal.TerminalApplication;
import top.codedance.iotp.tools.terminal.bean.ComConnectParam;
import top.codedance.iotp.tools.terminal.bean.SpliteStatus;
import top.codedance.iotp.tools.terminal.bean.WebsocketConnectParam;
import top.codedance.iotp.tools.terminal.comer.CallOwner;
import top.codedance.iotp.tools.terminal.comer.ComClient;
import top.codedance.iotp.tools.terminal.wser.WsClient;

import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import java.awt.*;
import java.awt.event.*;
import java.awt.im.InputContext;
import java.awt.im.spi.InputMethod;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.List;
import java.util.Timer;

/**
 * @author xuedianfu
 */
public class ShellFrame extends javax.swing.JFrame implements CallOwner {
    private WaitLoading waitLoading = new WaitLoading(this);
    public static Map<String, ComClient> ccs = new HashMap();
    public static Map<String, WsClient> wcs = new HashMap();
    private final String preSymbol = "$>";
    private List<String> cmds = new LinkedList<>();
    private int currentIndex = cmds.size() - 1;
    private ConnectionManager cm = null;
    private ClientPluginTester cpt = null;
    private HttpApiTester hat = null;
    private LogManage lm = null;
    private String xyw = "0";
    private boolean isManage = false;
    private boolean comProxy = false;
    private int comInstanceNum = 0;
    private SetNetwork sn = null;
    private ResetNetwork rn = null;
    private ModbusGen mg = null;
    private CertificateManage certificateManage = null;
    private SpliteStatus ss = new SpliteStatus(false, 0.8, 0);

    /**
     * Creates new form ShellFrame
     */
    public ShellFrame() {
        initComponents();
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosed(WindowEvent e) {
                System.exit(0);
            }
        });
        URL url = Thread.currentThread().getContextClassLoader().getResource("logo.gif");
        ImageIcon icon = new ImageIcon(url);
        setIconImage(icon.getImage());
        Map<String, Map<String, String>> params = TerminalApplication.readConfig();
        if (params.containsKey("request")) {
            Map<String, String> request = params.get("request");
            if (request.containsKey("type")) {
                jl_connectType.setText(request.get("type"));
            } else {
                jl_connectType.setText("http");
            }
            switchFormLable(jl_connectType.getText());
            jtf_url.setText(request.get("url"));
            jtf_deviceId.setText(request.get("deviceId"));
            jtf_username.setText(request.get("username"));
            jtf_password.setText(request.get("password"));
            if (request.containsKey("xyw")) {
                xyw = request.get("xyw");
            }
            if (request.containsKey("manage")) {
                isManage = Boolean.valueOf(request.get("manage"));
            }
        }
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                if (!ss.isMin()) {
                    ss.setPercentage(0.8);
                } else {
                    ss.setWidth(jSplitPane1.getParent().getWidth());
                }
                resetComponent();
            }
        });
        setLocationRelativeTo(null);
        setMinimumSize(new Dimension(1140, 643));
        setTitle("代码飞舞采控系统-系统控制终端");

        initConsole();
        resetComponent();
        initPos();
        initMenuBar();
        initMenus();
        initCmdHelp();
        initCmdHelpMenus();

        Timer t = new Timer();
        t.schedule(new TimerTask() {
            @Override
            public void run() {
                oprationConsolePreSymbol();

            }
        }, 100, 100);
    }

    private void initConsole(){
        jta_console.setCaretColor(Color.WHITE);
        jta_console.requestFocus(true);
        jta_console.append(preSymbol);
    }

    private void resetComponent(){
        if(ss.isMin()) {
            jSplitPane1.setDividerLocation(ss.getWidth());
        }else{
            jSplitPane1.setDividerLocation(ss.getPercentage());
        }
    }

    private void switchFormLable(String type) {
        this.jl_connectType.setText(type);
        if (type.equals("http") || type.equals("websocket")) {
            this.jLabel1.setText("接口地址：");
            this.jLabel4.setText("设备编号：");
            this.jLabel2.setText("用 户  名：");
            this.jLabel3.setText("密      码：");
            this.jtf_deviceId.removeKeyListener(keyListener);
            this.jtf_username.removeKeyListener(keyListener);
            this.jtf_password.removeKeyListener(keyListener);
        }
        if (type.equals("com")) {
            this.jLabel1.setText("串       口：");
            this.jLabel4.setText("波 特 率：");
            this.jLabel2.setText("数 据 位：");
            this.jLabel3.setText("停 止 位：");
            this.jtf_deviceId.addKeyListener(keyListener);
            this.jtf_username.addKeyListener(keyListener);
            this.jtf_password.addKeyListener(keyListener);
        }
    }

    private KeyListener keyListener = new KeyListener(){
        @Override
        public void keyTyped(KeyEvent e) {
            ShellFrame.this.keyTyped(e);
        }
        @Override
        public void keyPressed(KeyEvent e) { }
        @Override
        public void keyReleased(KeyEvent e) { }
    };

    private void keyTyped(KeyEvent evt){
        JTextField jtf = (JTextField)evt.getSource();
        if (!TerminalApplication.numbers.contains(evt.getKeyChar())) {
            evt.consume();
        }
        try{
            Integer.parseInt(jtf.getText());
            if(jtf.getText().startsWith("0")){
                jtf.setText(jtf.getText().replaceAll("^0+", ""));
            }
        }catch (Exception e){
            jtf.setText("0");
        }
    }

    public void loadConnnectSetting(JSONObject jo) {
        String type = jo.getString("type");
        switchFormLable(type);
        if (type.equals("http") || type.equals("websocket")) {
            this.jtf_url.setText(jo.getString("url"));
            this.jtf_deviceId.setText(jo.getString("deviceId"));
            this.jtf_username.setText(jo.getString("username"));
            this.jtf_password.setText(jo.getString("password"));
            this.xyw = jo.getString("0");
            this.comProxy = jo.getBoolean("comProxy");
            if(this.comProxy){
                this.comInstanceNum = jo.getInteger("comInstanceNum");
            }
        }
        if (type.equals("com")) {
            this.jtf_url.setText(jo.getJSONObject("com").getString("value"));
            this.jtf_deviceId.setText(jo.getString("btl"));
            this.jtf_username.setText(jo.getString("sjw"));
            this.jtf_password.setText(jo.getString("tzw"));
            this.xyw = jo.getString("xyw");
            this.isManage = jo.getBoolean("manage");
        }
    }

    public JSONObject exportConnectSetting() {
        JSONObject jo = new JSONObject();
        jo.put("type", jl_connectType.getText());
        jo.put("url", this.jtf_url.getText());
        jo.put("deviceId", this.jtf_deviceId.getText());
        jo.put("username", this.jtf_username.getText());
        jo.put("password", this.jtf_password.getText());
        jo.put("xyw", this.xyw);
        jo.put("manage", this.isManage);
        jo.put("comProxy", this.comProxy);
        if(this.comProxy){
            jo.put("comInstanceNum", this.comInstanceNum);
        }
        return jo;
    }

    private void initMenuBar() {
        JMenu jm = new JMenu("扩展功能");
        JMenuItem jmi3 = new JMenuItem("导入命令集");
        jmi3.addActionListener((event) -> {
            JFileChooser jfc = new JFileChooser();
            jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
            jfc.setFileFilter(new FileFilter() {
                @Override
                public boolean accept(File f) {
                    if (f.isDirectory())
                        return true;
                    return f.getName().endsWith(".txt");
                }
                @Override
                public String getDescription(){
                    return ".txt";
                }
            });
            int i = jfc.showOpenDialog(this);
            if(i == JFileChooser.APPROVE_OPTION){
                File selectedFile = jfc.getSelectedFile();
                if(selectedFile.exists() && selectedFile.isFile()) {
                    ArrayList<String> strings = SystemUtil.readFileToList(selectedFile.getAbsolutePath());
                    for (String cmd : strings) {
                        readCmds.add(cmd);
                    }
                    initCmdHelpData();
                    TerminalApplication.writeCmds(readCmds);
                    JOptionPane.showMessageDialog(this.getRootPane(), "导入成功");
                }else{
                    JOptionPane.showMessageDialog(this.getRootPane(), "请选取一个命令文本文件");
                }
            }
        });
        jm.add(jmi3);
        JMenuItem jmi4 = new JMenuItem("导出命令集");
        jmi4.addActionListener((event) -> {
            JFileChooser jfc = new JFileChooser();
            jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            int i = jfc.showOpenDialog(this);
            if(i == JFileChooser.APPROVE_OPTION) {
                File selectedFile = jfc.getSelectedFile();
                if(selectedFile.exists() && selectedFile.isDirectory()) {
                    ArrayList<String> strings = TerminalApplication.readCmds();
                    String data = "";
                    for (String cmd : strings) {
                        data += cmd + "\n";
                    }
                    String fileName = "iot-cmds.txt";
                    String filepath = selectedFile.getAbsolutePath() + File.separatorChar + fileName;
                    File f = new File(filepath);
                    if(!f.exists()){
                        try {
                            f.createNewFile();
                        } catch (IOException e) {
                            TerminalApplication.syslogInfo(e.getMessage());
                            JOptionPane.showMessageDialog(this.getRootPane(), "创建文件失败，请确保当前用户对所选目录有可写权限");
                        }
                    }
                    SystemUtil.writeFile(filepath, data);
                    JOptionPane.showMessageDialog(this.getRootPane(), "导出成功,文件是所选目录下的 " + fileName);
                }else{
                    JOptionPane.showMessageDialog(this.getRootPane(), "请选取一个文件夹");
                }
            }
        });
        jm.add(jmi4);
        JMenuItem jmi8 = new JMenuItem("文件上传");
        jmi8.addActionListener((event) -> {
            UploadFile uf = new UploadFile(this);
            uf.setLocationRelativeTo(ShellFrame.this);
            uf.setVisible(true);
        });
        jm.add(jmi8);
        JMenuItem jmi9 = new JMenuItem("文件下载");
        jmi9.addActionListener((event) -> {
            DownloadFile df = new DownloadFile(this);
            df.setLocationRelativeTo(ShellFrame.this);
            df.setVisible(true);
        });
        jm.add(jmi9);
        JMenuItem jmi = new JMenuItem("客户端连接");
        jmi.addActionListener((event) -> {
            if (ShellFrame.this.cm != null)
                cm.dispose();
            cm = new ConnectionManager(ShellFrame.this);
            cm.setLocationRelativeTo(ShellFrame.this);
            cm.setVisible(true);
        });
        jm.add(jmi);
        JMenuItem jmi2 = new JMenuItem("客户端插件测试器");
        jmi2.addActionListener((event) -> {
            if (ShellFrame.this.cpt != null)
                cpt.dispose();
            cpt = new ClientPluginTester(ShellFrame.this);
            cpt.setLocationRelativeTo(ShellFrame.this);
            cpt.setVisible(true);
        });
        jm.add(jmi2);
        JMenuItem jmi11 = new JMenuItem("HTTP接口测试器");
        jmi11.addActionListener((event) -> {
            if (ShellFrame.this.hat != null)
                hat.dispose();
            hat = new HttpApiTester(ShellFrame.this);
            hat.setLocationRelativeTo(ShellFrame.this);
            hat.setVisible(true);
        });
        jm.add(jmi11);
        JMenuItem jmi5 = new JMenuItem("运行日志");
        jmi5.addActionListener((event) -> {
            if (ShellFrame.this.lm != null)
                lm.dispose();
            lm = new LogManage(ShellFrame.this);
            lm.setLocationRelativeTo(ShellFrame.this);
            lm.setVisible(true);
        });
        jm.add(jmi5);
        JMenuItem jmi6 = new JMenuItem("版本信息");
        jmi6.addActionListener((event) -> {
            String ver = TerminalApplication.version.toString();
            String firstPart = ver.substring(0, ver.length() - 1);
            String firstPart1 = firstPart.substring(0, 1);
            String firstPart2 = firstPart.substring(1, 2);
            String firstPart3 = firstPart.substring(2, firstPart.length() - 8);
            String firstPart4 = firstPart.substring(firstPart.length() - 8);
            String secondPart = ver.substring(ver.length() - 1);
            secondPart = VersionFileUtil.VersionName.valueOf(Integer.valueOf(secondPart)).toString();
            JOptionPane.showMessageDialog(this.getRootPane(), "当前版本为：" + firstPart1 + "." + firstPart2 + "." + firstPart3 + "." + firstPart4 + "-" + secondPart);
        });
        jm.add(jmi6);
        this.jmb.add(jm);
        JMenu jm1 = new JMenu("工具");
        JMenuItem jmi1 = new JMenuItem("证书管理器");
        jmi1.addActionListener((event) -> {
            if (ShellFrame.this.certificateManage != null)
                certificateManage.dispose();
            certificateManage = new CertificateManage(ShellFrame.this);
            certificateManage.setLocationRelativeTo(ShellFrame.this);
            certificateManage.setVisible(true);
        });
        jm1.add(jmi1);
        JMenuItem jmi10 = new JMenuItem("国密SM2密钥及密码生成器");
        jmi10.addActionListener((event) -> {
            UserVerificationCertificateManager uvcm = new UserVerificationCertificateManager(ShellFrame.this);
            uvcm.setLocationRelativeTo(ShellFrame.this);
            uvcm.setVisible(true);
        });
        jm1.add(jmi10);
        JMenuItem jmi7 = new JMenuItem("Hex-ASCII互转");
        jmi7.addActionListener((event) -> {
            Hex2AsciiFrame haf = new Hex2AsciiFrame(this);
            haf.setLocationRelativeTo(ShellFrame.this);
            haf.setVisible(true);
        });
        jm1.add(jmi7);
        JMenuItem jmi12 = new JMenuItem("服务端管理工具");
        jmi12.addActionListener((event) -> {
            new Thread(new ServerToolApplication(ShellFrame.this)).start();
        });
        jm1.add(jmi12);
        this.jmb.add(jm1);
        JMenu jm2 = new JMenu("设置");
        JMenuItem jmi13 = new JMenuItem("软件风格");
        jmi13.addActionListener((event) -> {
            SetSkin setSkin = new SetSkin(this);
            setSkin.setVisible(true);
        });
        jm2.add(jmi13);
        this.jmb.add(jm2);
        this.setJMenuBar(this.jmb);
    }

    private DefaultListModel dlmB;
    private ArrayList<String> readCmds;

    private void initCmdHelp() {
        dlmB = new DefaultListModel();
        readCmds = TerminalApplication.readCmds();
        this.jl_cmd.setModel(dlmB);
        initCmdHelpData();
    }

    private void initCmdHelpData() {
        dlmB.clear();
        for (String cmd : readCmds) {
            dlmB.addElement(cmd);
        }
        this.jl_cmd.repaint();
    }

    private JPopupMenu cmdHelpJpm;

    private void initCmdHelpMenus() {
        cmdHelpJpm = new JPopupMenu();
        JMenuItem mi_del = new JMenuItem("删除");
        mi_del.setOpaque(true);
        mi_del.setBackground(new java.awt.Color(255, 51, 51));
        mi_del.setForeground(new java.awt.Color(255, 255, 255));
        mi_del.addActionListener(e -> {
            readCmds.remove(jl_cmd.getSelectedValue());
            initCmdHelpData();
            TerminalApplication.writeCmds(readCmds);
        });
        cmdHelpJpm.add(mi_del, 0);
        cmdHelpJpm.add(new JPopupMenu.Separator(), 1);
        JMenuItem mi_restartSystem = new JMenuItem("重启系统");
        mi_restartSystem.addActionListener(e -> {
            addCmd("shutdown /r /t 0");
        });
        cmdHelpJpm.add(mi_restartSystem, 2);
        JMenuItem mi_shutdownSystem = new JMenuItem("关闭系统");
        mi_shutdownSystem.addActionListener(e -> {
            addCmd("shutdown /s /t 0");
        });
        cmdHelpJpm.add(mi_shutdownSystem, 3);
        JMenuItem mi_startRemoteDesktopServices = new JMenuItem("开启远程桌面服务");
        mi_startRemoteDesktopServices.addActionListener(e -> {
            addCmd("net start \"Remote Desktop Services\" /yes");
        });
        cmdHelpJpm.add(mi_startRemoteDesktopServices, 4);
        JMenuItem mi_stopRemoteDesktopServices = new JMenuItem("关闭远程桌面服务");
        mi_stopRemoteDesktopServices.addActionListener(e -> {
            addCmd("net stop \"Remote Desktop Services\" /yes");
        });
        cmdHelpJpm.add(mi_stopRemoteDesktopServices, 5);
        JMenuItem mi_disableRemoteDesktopServices = new JMenuItem("禁用远程桌面服务");
        mi_disableRemoteDesktopServices.addActionListener(e -> {
            addCmd("net config \"Remote Desktop Services\" start=disabled /yes");
        });
        cmdHelpJpm.add(mi_disableRemoteDesktopServices, 6);
        JMenuItem mi_enableRemoteDesktopServices = new JMenuItem("启用远程桌面服务");
        mi_enableRemoteDesktopServices.addActionListener(e -> {
            addCmd("net config \"Remote Desktop Services\" start=auto /yes");
        });
        cmdHelpJpm.add(mi_enableRemoteDesktopServices, 7);
        JMenuItem mi_demandRemoteDesktopServices = new JMenuItem("手动操作远程桌面服务");
        mi_demandRemoteDesktopServices.addActionListener(e -> {
            addCmd("net config \"Remote Desktop Services\" start=demand /yes");
        });
        cmdHelpJpm.add(mi_demandRemoteDesktopServices, 8);
        JMenuItem mi_netNetwork = new JMenuItem("配置网络命令...");
        mi_netNetwork.addActionListener(e -> {
            sn = new SetNetwork(this);
            sn.initData(jl_cmd.getSelectedValue());
            sn.setVisible(true);
        });
        cmdHelpJpm.add(mi_netNetwork, 9);
        JMenuItem mi_resetNetwork = new JMenuItem("重置网络命令...");
        mi_resetNetwork.addActionListener(e -> {
            rn = new ResetNetwork(this);
            rn.initData(jl_cmd.getSelectedValue());
            rn.setVisible(true);
        });
        cmdHelpJpm.add(mi_resetNetwork, 10);
        JMenuItem mi_enterCommandLineMode = new JMenuItem("配置WIN系统进入命令行模式");
        mi_enterCommandLineMode.addActionListener(e -> {
            addCmd("REG ADD \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /t REG_SZ /v shell /d \"cmd.exe\" /f");
        });
        cmdHelpJpm.add(mi_enterCommandLineMode, 11);
        JMenuItem mi_enterDesktopMode = new JMenuItem("配置WIN系统进入桌面模式");
        mi_enterDesktopMode.addActionListener(e -> {
            addCmd("REG ADD \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /t REG_SZ /v shell /d \"explorer.exe\" /f");
        });
        cmdHelpJpm.add(mi_enterDesktopMode, 12);
        JMenuItem mi_cancelDesktopMode = new JMenuItem("取消WIN系统进入某种模式");
        mi_cancelDesktopMode.addActionListener(e -> {
            addCmd("REG DELETE \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v shell /f");
        });
        cmdHelpJpm.add(mi_cancelDesktopMode, 13);
        JMenuItem mi_commandLineLoginMode = new JMenuItem("配置WIN系统命令行登陆模式");
        mi_commandLineLoginMode.addActionListener(e -> {
            addCmd("REG ADD \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Authentication\\LogonUI\\TestHooks\" /t REG_DWORD /v ConsoleMode /d \"1\" /f");
        });
        cmdHelpJpm.add(mi_commandLineLoginMode, 14);
        JMenuItem mi_cancelCommandLineLoginMode = new JMenuItem("取消WIN系统命令行登陆模式");
        mi_cancelCommandLineLoginMode.addActionListener(e -> {
            addCmd("REG DELETE \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Authentication\\LogonUI\\TestHooks\" /v ConsoleMode /f");
        });
        cmdHelpJpm.add(mi_cancelCommandLineLoginMode, 15);
        cmdHelpJpm.add(new JPopupMenu.Separator(), 16);
        JMenuItem modbus_gen = new JMenuItem("Modbus命令生成器");
        modbus_gen.addActionListener(e -> {
            mg = new ModbusGen(this);
            mg.setVisible(true);
        });
        cmdHelpJpm.add(modbus_gen, 17);
        jl_cmd.add(cmdHelpJpm);
    }

    private JPopupMenu jpm;

    private void initMenus() {
        jpm = new JPopupMenu();
        JMenuItem mi_copy = new JMenuItem("复制");
        mi_copy.addActionListener(e -> {
            jta_console.copy();
        });
        jpm.add(mi_copy);
        JMenuItem mi_cut = new JMenuItem("剪切");
        mi_cut.addActionListener(e -> {
            jta_console.cut();
            try {
                int offset = jta_console.getLineOfOffset(jta_console.getCaretPosition());
                int start = jta_console.getLineStartOffset(offset);
                int end = jta_console.getLineEndOffset(offset);
                if (jta_console.getText(start, (end - start)).equals("")) {
                    jta_console.append(preSymbol);
                    initPos();
                }
            } catch (BadLocationException ex) {
                TerminalApplication.syslogInfo(ex.getMessage());
            }
        });
        jpm.add(mi_cut);
        JMenuItem mi_allSelect = new JMenuItem("全选");
        mi_allSelect.addActionListener(e -> {
            jta_console.selectAll();
        });
        jpm.add(mi_allSelect);
        JMenuItem mi_pase = new JMenuItem("粘贴");
        mi_pase.addActionListener(e -> {
            jta_console.paste();
        });
        jpm.add(mi_pase);
        JMenuItem mi_del = new JMenuItem("删除");
        mi_del.addActionListener(e -> {
            jta_console.replaceSelection(null);
            try {
                int offset = jta_console.getLineOfOffset(jta_console.getCaretPosition());
                int start = jta_console.getLineStartOffset(offset);
                int end = jta_console.getLineEndOffset(offset);
                if (jta_console.getText(start, (end - start)).equals("")) {
                    jta_console.append(preSymbol);
                    initPos();
                }
            } catch (BadLocationException ex) {
                TerminalApplication.syslogInfo(ex.getMessage());
            }
        });
        jpm.add(mi_del);
        jta_console.add(jpm);
    }

    /**
     * 添加命令并永久保存
     * @param cmd
     */
    public void addCmd(String cmd){
        readCmds.add(cmd);
        initCmdHelpData();
        TerminalApplication.writeCmds(readCmds);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jmb = new javax.swing.JMenuBar();
        jPanel1 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jtf_url = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        jtf_username = new javax.swing.JTextField();
        jLabel3 = new javax.swing.JLabel();
        jtf_password = new javax.swing.JTextField();
        jLabel4 = new javax.swing.JLabel();
        jtf_deviceId = new javax.swing.JTextField();
        jb_save = new javax.swing.JButton();
        jcb_powershell = new javax.swing.JCheckBox();
        jcb_savecmd = new javax.swing.JCheckBox();
        jLabel5 = new javax.swing.JLabel();
        jl_connectType = new javax.swing.JLabel();
        jSeparator1 = new javax.swing.JSeparator();
        jPanel2 = new javax.swing.JPanel();
        jpb_request = new javax.swing.JProgressBar();
        jSplitPane1 = new javax.swing.JSplitPane();
        jScrollPane2 = new javax.swing.JScrollPane();
        jl_cmd = new javax.swing.JList<>();
        jScrollPane1 = new javax.swing.JScrollPane();
        jta_console = new javax.swing.JTextArea();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowDeactivated(java.awt.event.WindowEvent evt) {
                formWindowDeactivated(evt);
            }
        });

        jPanel1.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));

        jLabel1.setText("接口地址：");

        jtf_url.setText("https://127.0.0.1");
        jtf_url.setToolTipText("");

        jLabel2.setText("用 户 名：");
        jLabel2.setToolTipText("");

        jLabel3.setText("密      码：");
        jLabel3.setToolTipText("");

        jLabel4.setText("设备编号：");

        jtf_deviceId.setText("d1");

        jb_save.setText("保存配置");
        jb_save.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jb_saveActionPerformed(evt);
            }
        });

        jcb_powershell.setText("执行PowerShell命令");

        jcb_savecmd.setText("保存到命令区");
        jcb_savecmd.setActionCommand("");

        jLabel5.setText("连接类型：");
        jLabel5.setToolTipText("");

        jl_connectType.setBackground(new java.awt.Color(0, 0, 0));
        jl_connectType.setFont(new java.awt.Font("Microsoft YaHei UI", 1, 14)); // NOI18N
        jl_connectType.setForeground(new java.awt.Color(255, 255, 255));
        jl_connectType.setText("http");
        jl_connectType.setOpaque(true);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGap(23, 23, 23)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(jtf_username)
                    .addComponent(jtf_url, javax.swing.GroupLayout.DEFAULT_SIZE, 317, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel4)
                    .addComponent(jLabel3))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jtf_password, javax.swing.GroupLayout.DEFAULT_SIZE, 333, Short.MAX_VALUE)
                    .addComponent(jtf_deviceId))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(jcb_savecmd, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel5)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jl_connectType))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(jcb_powershell, javax.swing.GroupLayout.PREFERRED_SIZE, 134, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jb_save)))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(jtf_url, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel4)
                    .addComponent(jtf_deviceId)
                    .addComponent(jcb_savecmd)
                    .addComponent(jLabel5)
                    .addComponent(jl_connectType))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(jtf_username, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel3)
                    .addComponent(jtf_password, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jb_save)
                    .addComponent(jcb_powershell))
                .addContainerGap())
        );

        jSeparator1.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));

        jPanel2.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));

        jSplitPane1.setDividerLocation(-20);
        jSplitPane1.setToolTipText("");
        jSplitPane1.setCursor(new java.awt.Cursor(java.awt.Cursor.MOVE_CURSOR));

        jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        jScrollPane2.setPreferredSize(new java.awt.Dimension(200, 100));

        jl_cmd.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        jl_cmd.setName(""); // NOI18N
        jl_cmd.setPreferredSize(null);
        jl_cmd.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jl_cmdMouseClicked(evt);
            }
            public void mousePressed(java.awt.event.MouseEvent evt) {
                jl_cmdMousePressed(evt);
            }
        });
        jScrollPane2.setViewportView(jl_cmd);

        jSplitPane1.setRightComponent(jScrollPane2);

        jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        jScrollPane1.setPreferredSize(new java.awt.Dimension(500, 100));

        jta_console.setBackground(new java.awt.Color(51, 51, 51));
        jta_console.setColumns(20);
        jta_console.setFont(new java.awt.Font("微软雅黑", 0, 14)); // NOI18N
        jta_console.setForeground(new java.awt.Color(0, 153, 102));
        jta_console.setLineWrap(true);
        jta_console.setRows(5);
        jta_console.setWrapStyleWord(true);
        jta_console.setCursor(new java.awt.Cursor(java.awt.Cursor.TEXT_CURSOR));
        jta_console.setDisabledTextColor(new java.awt.Color(255, 255, 255));
        jta_console.setMinimumSize(new java.awt.Dimension(500, 0));
        jta_console.setPreferredSize(null);
        jta_console.addCaretListener(new javax.swing.event.CaretListener() {
            public void caretUpdate(javax.swing.event.CaretEvent evt) {
                jta_consoleCaretUpdate(evt);
            }
        });
        jta_console.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                jta_consoleFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                jta_consoleFocusLost(evt);
            }
        });
        jta_console.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jta_consoleMouseClicked(evt);
            }
            public void mousePressed(java.awt.event.MouseEvent evt) {
                jta_consoleMousePressed(evt);
            }
        });
        jta_console.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                jta_consoleKeyPressed(evt);
            }
            public void keyReleased(java.awt.event.KeyEvent evt) {
                jta_consoleKeyReleased(evt);
            }
            public void keyTyped(java.awt.event.KeyEvent evt) {
                jta_consoleKeyTyped(evt);
            }
        });
        jScrollPane1.setViewportView(jta_console);

        jSplitPane1.setLeftComponent(jScrollPane1);

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jpb_request, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
            .addComponent(jSplitPane1, javax.swing.GroupLayout.Alignment.TRAILING)
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
                .addComponent(jpb_request, javax.swing.GroupLayout.PREFERRED_SIZE, 9, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 541, Short.MAX_VALUE)
                .addContainerGap())
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jSeparator1))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 6, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private boolean isDisableBackspace = false;
    private boolean isDisableAllkey = false;
    private int startPos;
    private long lastCtrlCKeyDownTime = 0;
    private boolean ctrlPressed = false;
    private boolean emptyEnter = false;
    private boolean isSubmiting = false;

    private void jta_consoleKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jta_consoleKeyPressed
        if (evt.getKeyCode() == KeyEvent.VK_CONTROL) {
            ctrlPressed = true;
        }
        if (evt.getKeyChar() == 8) { //退格键
            if (isDisableBackspace || !getCaretIsLastLine() || getCaretIsLastLineAndSecondColumn()) {
                evt.consume();
            }
        }
        if (evt.getKeyCode() == KeyEvent.VK_DELETE) { //del键
            if (isDisableAllkey) {
                evt.consume();
            }
        }
        if (evt.getKeyCode() == KeyEvent.VK_ENTER) { //回车键
            if (isDisableAllkey) {
                evt.consume();
            }
        }
        if (evt.getKeyCode() == KeyEvent.VK_TAB) { //tag键
            evt.consume();
        }
        if (evt.getKeyCode() == KeyEvent.VK_UP) { //上键
            evt.consume();
            Document document = jta_console.getDocument();
            try {
                document.remove(startPos, document.getLength() - startPos);
            } catch (Exception ex) {
                TerminalApplication.syslogInfo(ex.getMessage());
            }
            currentIndex--;
            if (currentIndex < 0) {
                currentIndex = 0;
            }
            if(currentIndex < cmds.size()) {
                jta_console.append(cmds.get(currentIndex));
                jta_console.setCaretPosition(jta_console.getDocument().getLength());
            }
        }
        if (evt.getKeyCode() == KeyEvent.VK_DOWN) { //下键
            evt.consume();
            Document document = jta_console.getDocument();
            try {
                document.remove(startPos, document.getLength() - startPos);
            } catch (Exception ex) {
                TerminalApplication.syslogInfo(ex.getMessage());
            }
            currentIndex++;
            if (currentIndex >= cmds.size()) {
                currentIndex = cmds.size() - 1;
            }
            if(currentIndex < cmds.size()) {
                jta_console.append(cmds.get(currentIndex));
                jta_console.setCaretPosition(jta_console.getDocument().getLength());
            }
        }
        if (evt.isControlDown() && evt.getKeyCode() == KeyEvent.VK_C) { //ctrl+c
            if(System.currentTimeMillis() - lastCtrlCKeyDownTime < 500) {
                jta_console.append("\n");
                jta_console.append(preSymbol);
                initPos();
            }else{
                jta_console.copy();
            }
            lastCtrlCKeyDownTime = System.currentTimeMillis();
        }
    }//GEN-LAST:event_jta_consoleKeyPressed

    private void jta_consoleCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_jta_consoleCaretUpdate
        try {
            int row = jta_console.getLineOfOffset(evt.getDot());
            int column = evt.getDot() - jta_console.getLineStartOffset(row);
            if (evt.getDot() < jta_console.getText().length()) {
                if (column <= 2) {
                    isDisableBackspace = true;
                } else {
                    isDisableBackspace = false;
                }
                isDisableAllkey = true;
            } else {
                if (column <= 2) {
                    isDisableBackspace = true;
                } else {
                    isDisableBackspace = false;
                }
                isDisableAllkey = false;
            }
        } catch (Exception e2) {
            TerminalApplication.syslogInfo(e2.getMessage());
        }
    }//GEN-LAST:event_jta_consoleCaretUpdate

    private void jta_consoleKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jta_consoleKeyTyped
        if(!getCaretIsLastLine() || emptyEnter || isSubmiting){
            evt.consume();
        }
        if (evt.getKeyChar() == '\n') { //回车键
            if (!isDisableAllkey && !isSubmiting) {
                execCommand();
            }
        }
        if (evt.getKeyChar() == '\t') { //tag键
            if (!isDisableAllkey) {
                String currentCommand = getCurrentCommand(1);
                Iterator<String> iterator = cmds.iterator();
                while (iterator.hasNext()) {
                    String next = iterator.next();
                    if (next.startsWith(currentCommand)) {
                        jta_console.append(next.replace(currentCommand, ""));
                        break;
                    }
                }
            }
        }
    }//GEN-LAST:event_jta_consoleKeyTyped

    private void jb_saveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jb_saveActionPerformed
        Map<String, Map<String, String>> params = new HashMap<>();
        Map<String, String> request = new HashMap<>();
        request.put("type", jl_connectType.getText());
        request.put("url", jtf_url.getText());
        request.put("deviceId", jtf_deviceId.getText());
        request.put("username", jtf_username.getText());
        request.put("password", jtf_password.getText());
        request.put("xyw", this.xyw);
        request.put("manage", String.valueOf(this.isManage));
        params.put("request", request);
        try {
            TerminalApplication.saveConfig(params);
            JOptionPane.showMessageDialog(this.getRootPane(), "保存成功");
        } catch (Exception ex) {
            TerminalApplication.syslogInfo(ex.getMessage());
            JOptionPane.showMessageDialog(this.getRootPane(), "保存失败");
        }
    }//GEN-LAST:event_jb_saveActionPerformed

    private void jta_consoleMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jta_consoleMousePressed
        int mods = evt.getModifiers();
        if ((mods & InputEvent.BUTTON3_MASK) != 0) {
            if (this.getExtendedState() == Frame.MAXIMIZED_BOTH) {
                this.jpm.show(this, evt.getX(), evt.getYOnScreen());
            } else {
                this.jpm.show(this.jta_console, evt.getX(), evt.getY());
            }
        }
    }//GEN-LAST:event_jta_consoleMousePressed

    private void jl_cmdMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jl_cmdMouseClicked
        if (evt.getClickCount() == 2) {
            this.jta_console.append(this.jl_cmd.getSelectedValue());
        }
    }//GEN-LAST:event_jl_cmdMouseClicked

    private void jl_cmdMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jl_cmdMousePressed
        int mods = evt.getModifiers();
        if ((mods & InputEvent.BUTTON3_MASK) != 0) {
            if (this.getExtendedState() == Frame.MAXIMIZED_BOTH) {
                this.cmdHelpJpm.show(this, this.jta_console.getWidth() - this.cmdHelpJpm.getWidth() / 3, evt.getYOnScreen());
            } else {
                this.cmdHelpJpm.show(this, evt.getX() + this.jta_console.getWidth(), evt.getY() + this.cmdHelpJpm.getHeight() / 2);
            }
        }
    }//GEN-LAST:event_jl_cmdMousePressed

    private void jta_consoleFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_jta_consoleFocusLost
//        jta_console.getInputContext().selectInputMethod(Locale.getDefault());
        InputContext context = jta_console.getInputContext();
        InputMethod method = (InputMethod)context.getInputMethodControlObject();
        if(method != null) {
            method.setLocale(Locale.CHINESE);
        }
    }//GEN-LAST:event_jta_consoleFocusLost

    private void jta_consoleFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_jta_consoleFocusGained
        InputContext context = jta_console.getInputContext();
        InputMethod method = (InputMethod)context.getInputMethodControlObject();
        if(method != null) {
            method.setLocale(Locale.ENGLISH);
        }
    }//GEN-LAST:event_jta_consoleFocusGained

    private void formWindowDeactivated(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowDeactivated
//        jta_console.getInputContext().selectInputMethod(Locale.getDefault());
        InputContext context = jta_console.getInputContext();
        InputMethod method = (InputMethod)context.getInputMethodControlObject();
        if(method != null) {
            method.setLocale(Locale.CHINESE);
        }
    }//GEN-LAST:event_formWindowDeactivated

    private void jta_consoleMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jta_consoleMouseClicked
        if (ctrlPressed && evt.getClickCount() == 2) {
            if (jSplitPane1.getParent().getWidth() - jSplitPane1.getDividerLocation() < 100) {
                ss.setMin(false);
                ss.setPercentage(0.8);
            } else {
                ss.setMin(true);
                ss.setWidth(jSplitPane1.getParent().getWidth());
            }
            resetComponent();
            evt.consume();
            jta_console.setSelectionStart(jta_console.getSelectionEnd());
        }
    }//GEN-LAST:event_jta_consoleMouseClicked

    private void jta_consoleKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jta_consoleKeyReleased
        if (evt.getKeyCode() == KeyEvent.VK_CONTROL) {
            ctrlPressed = false;
        }
    }//GEN-LAST:event_jta_consoleKeyReleased

    private void waiting(){
        waitLoading.open();
    }

    private void over(){
        if(waitLoading != null) {
            waitLoading.close();
        }
    }

    /**
     * 直接把命令放到当前终端
     * @param cmd
     */
    public void appendCmd(String cmd){
        this.jta_console.append(cmd);
    }

    /**
     * CLS后初始化命令终端
     */
    private void initConsolePreSymbol(){
        jta_console.setText("");
        jta_console.append(preSymbol);
        initPos();
        appendResultLastTime = 0;
        emptyEnter = false;
        isSubmiting = false;
    }

    /**
     * 提交完成后初始化命令终端
     */
    private void submitEnd(){
        if(!emptyEnter) {
            jta_console.append("\n");
        }
        jta_console.append(preSymbol);
        initPos();
        appendResultLastTime = 0;
        emptyEnter = false;
        isSubmiting = false;
    }

    private long appendResultLastTime = 0;
    private long exceptionLastTime = 0;
    private void oprationConsolePreSymbol(){
        if(isFocused() && !getCaretIsLastLineAndSecondColumn()){
            if(appendResultLastTime != 0 && System.currentTimeMillis() - appendResultLastTime > 3000){
                submitEnd();
            }
            if(emptyEnter){
                submitEnd();
            }
        }
        if(isInitPosition()){
            exceptionLastTime = System.currentTimeMillis();
        }
        if(!isInitPosition() && exceptionLastTime != 0 && System.currentTimeMillis() - exceptionLastTime > 30000){
            submitEnd();
            exceptionLastTime = 0;
        }
    }

    /**
     * 添加结果
     *
     * @param result
     */
    public void appendResult(String result) {
        over();
        if (result != null) {
            if(!result.isEmpty() && !result.endsWith("\n")) {
                jta_console.append("\n");
            }
            jta_console.append(result);
            appendResultLastTime = System.currentTimeMillis();
            initPos();
        }
    }

    @Override
    public void appendError(String data) {
        over();
        if (data != null) {
            if(!data.isEmpty() && !data.endsWith("\n")) {
                jta_console.append("\n");
            }
            jta_console.append(data);
            appendResultLastTime = System.currentTimeMillis();
            initPos();
            TerminalApplication.syslogInfo(data);
        }
    }

    @Override
    public String getOwnerClassName(){
        return this.getClass().getTypeName();
    }

    //判断光标是否在等待输命令状态
    private boolean isInitPosition(){
        try {
            int lineCount = jta_console.getLineCount(); //总行数
            int c = jta_console.getCaretPosition();
            int currentLine = jta_console.getLineOfOffset(c) + 1; //当前所在行数
            int currentCol = c - jta_console.getLineStartOffset(currentLine - 1) + 1;//当前所在列数
            return lineCount == currentLine && currentCol == 3;
        }catch (Exception e){
            return false;
        }
    }

    /**
     * 获取光标是否在最后一行的第二列
     * @return
     */
    private boolean getCaretIsLastLineAndSecondColumn(){
        try {
            int caretPosition = jta_console.getCaretPosition();
            int lineOfOffset = jta_console.getLineOfOffset(caretPosition);
            int lineCount = jta_console.getLineCount();
            if(lineOfOffset == lineCount - 1){
                int col = caretPosition - jta_console.getLineStartOffset(lineOfOffset) + 1;
                return col == 2;
            }else{
                return false;
            }
        }catch (Exception e){
            TerminalApplication.syslogInfo(e.getMessage());
            return false;
        }
    }

    /**
     * 获取光标是否在最后一行
     * @return
     */
    private boolean getCaretIsLastLine(){
        try {
            int caretPosition = jta_console.getCaretPosition();
            int lineOfOffset = jta_console.getLineOfOffset(caretPosition);
            int lineCount = jta_console.getLineCount();
            return lineOfOffset == lineCount - 1;
        }catch (Exception e){
            TerminalApplication.syslogInfo(e.getMessage());
            return false;
        }
    }

    /**
     * 获取当前输入的命令
     * @param offset
     * @return
     */
    private String getCurrentCommand(int offset){
        try {
            Element paragraph = jta_console.getDocument().getDefaultRootElement();
            int contentCount = paragraph.getElementCount();
            Element e = paragraph.getElement(contentCount - offset);
            int rangeStart = e.getStartOffset();
            int rangeEnd = e.getEndOffset();
            String commandLine = jta_console.getText(rangeStart, rangeEnd - rangeStart);
            String prefix = commandLine.substring(0, 2).trim();
            if(!prefix.equals(preSymbol)){
                return null;
            }
            return commandLine.substring(2).trim();
        }catch (Exception e){
            TerminalApplication.syslogInfo(e.getMessage());
            return null;
        }
    }

    /**
     * 执行命令
     */
    private void execCommand() {
        String result = null;
        try {
            final String cmd = getCurrentCommand(2);
            if (cmd != null && !cmd.isEmpty()) {
                isSubmiting = true;
                jta_console.setEditable(false);
                jpb_request.setIndeterminate(true);
                if ("clear".equals(cmd) || "cls".equals(cmd)) {
                    initConsolePreSymbol();
                } else if ("exit".equals(cmd)) {
                    System.exit(0);
                } else {
                    cmds.add(cmd);
                    currentIndex = cmds.size();
                    String connectType = this.jl_connectType.getText();
                    if (connectType.equals("http")) {
                        waiting();
                        TerminalApplication.pool.submit(() -> {
                            String result2 = null;
                            StandandService standandService = new StandandService(jtf_url.getText(), jtf_deviceId.getText());
                            JSONObject jsonObject;
                            if(!this.comProxy) {
                                ExecSystemParam execSystemParam = new ExecSystemParam();
                                execSystemParam.setUsername(jtf_username.getText());
                                execSystemParam.setPassword(jtf_password.getText());
                                if (jcb_powershell.isSelected()) {
                                    PowershellSubParam powershellSubParam = new PowershellSubParam();
                                    powershellSubParam.setCmd(cmd);
                                    powershellSubParam.setPowershell(true);
                                    execSystemParam.setCommand(powershellSubParam);
                                } else {
                                    execSystemParam.setCommand(cmd);
                                }
                                jsonObject = standandService.ExecSystem(execSystemParam);
                            }else{
                                ExecComParam execComParam = new ExecComParam();
                                execComParam.setUsername(jtf_username.getText());
                                execComParam.setPassword(jtf_password.getText());
                                ComClientParam comClientParam = new ComClientParam();
                                comClientParam.setId(this.comInstanceNum);
                                JSONObject tmpJo = new JSONObject();
                                tmpJo.put("cmd", cmd);
                                if (jcb_powershell.isSelected()) {
                                    tmpJo.put("powershell", true);
                                }
                                comClientParam.setCommand(tmpJo.toJSONString());
                                execComParam.setClient(comClientParam);
                                jsonObject = standandService.execCom(execComParam);
                            }
                            if (jsonObject.getIntValue("status") == 200) {
                                JSONObject tmpResult = jsonObject.getJSONObject("data");
                                if (tmpResult.getBoolean("ok")) {
                                    if (tmpResult.containsKey("context")) {
                                        result2 = tmpResult.getString("context");
                                        try{
                                            JSONObject subJo = JSON.parseObject(result2);
                                            if(subJo.containsKey("ok") && subJo.getBoolean("ok")){
                                                result2 = subJo.getString("context");
                                            }else{
                                                result2 = subJo.getString("msg");
                                            }
                                        }catch (Exception exc){}
                                    } else {
                                        result2 = "Success";
                                    }
                                } else {
                                    if (tmpResult.containsKey("msg")) {
                                        result2 = tmpResult.getString("msg");
                                    }
                                }
                                if (jcb_savecmd.isSelected() && !readCmds.contains(cmd)) {
                                    readCmds.add(cmd);
                                    initCmdHelpData();
                                    TerminalApplication.writeCmds(readCmds);
                                }
                            } else {
                                result2 = jsonObject.getString("message");
                            }
                            appendResult(result2);
                        });
                    }
                    if (connectType.equals("com")) {
                        waiting();
                        TerminalApplication.pool.submit(() -> {comSendCmd(cmd);});
                    }
                    if (connectType.equals("websocket")) {
                        waiting();
                        TerminalApplication.pool.submit(() -> {wsSendCmd(cmd);});
                    }
                }
            }else{
                emptyEnter = true;
            }
        } catch (Exception ex) {
            submitEnd();
        } finally {
            if(result != null) {
                appendResult(result);
            }
            jta_console.setEditable(true);
            jpb_request.setIndeterminate(false);
        }
    }

    /**
     * websocket发送命令
     * @param cmd
     */
    private void wsSendCmd(String cmd){
        getWsClient();
        this.wcs.get(getWsId()).send(cmd);
    }

    /**
     * 获取websocket客户端唯一标识
     * @return
     */
    private String getWsId(){
        return this.jtf_url.getText() + "_" + this.jtf_deviceId.getText();
    }

    /**
     * 创建websocket客户端
     */
    public void createWsClient(){
        WsClient wsClient = new WsClient(this, new WebsocketConnectParam(this.jtf_url.getText(), this.jtf_username.getText(), this.jtf_password.getText(), this.jtf_deviceId.getText(), jcb_powershell.isSelected()));
        wsClient.send("echo Welcom");
        this.wcs.put(getWsId(), wsClient);
        wsClient.waiting(1);
    }

    /**
     * 获取websocket客户端
     */
    private void getWsClient(){
        if (!this.wcs.containsKey(getWsId())) {
            createWsClient();
        }else{
            WsClient wsClient = this.wcs.get(getWsId());
            wsClient.setOwner(this);
            if(!wsClient.isOpen()){
                this.wcs.remove(getWsId());
                createWsClient();
            }
        }
    }

    /**
     * 串口发送命令
     * @param cmd
     */
    private void comSendCmd(String cmd){
        getComClient();
        if(this.isManage) {
            JSONObject command = new JSONObject();
            command.put("cmd", cmd);
            if (jcb_powershell.isSelected()) {
                command.put("powershell", true);
            }
            cmds.add(cmd);
            currentIndex = cmds.size();
            this.ccs.get(this.jtf_url.getText()).send(command.toJSONString());
        }else{
            byte[] bytes = HexUtil.toBytes(cmd.replaceAll("\\s+", ""));
            this.ccs.get(this.jtf_url.getText()).send(bytes);
        }
    }

    /**
     * 创建客户端
     */
    private void createComClient(){
        this.ccs.put(this.jtf_url.getText(), new ComClient(this, new ComConnectParam(this.jtf_url.getText(), Integer.parseInt(this.jtf_deviceId.getText()), Integer.parseInt(this.jtf_username.getText()), Integer.parseInt(this.jtf_password.getText()), Integer.parseInt(this.xyw))));
    }

    /**
     * 获取客户端
     */
    private void getComClient(){
        if (!this.ccs.containsKey(this.jtf_url.getText())) {
            createComClient();
        }else{
            ComClient comClient = this.ccs.get(this.jtf_url.getText());
            comClient.setOwner(this);
        }
    }

    private void initPos() {
        int pos = jta_console.getDocument().getLength();
        jta_console.setCaretPosition(pos);
        startPos = pos;
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JButton jb_save;
    private javax.swing.JCheckBox jcb_powershell;
    private javax.swing.JCheckBox jcb_savecmd;
    private javax.swing.JList<String> jl_cmd;
    private javax.swing.JLabel jl_connectType;
    private javax.swing.JMenuBar jmb;
    private javax.swing.JProgressBar jpb_request;
    private javax.swing.JTextArea jta_console;
    private javax.swing.JTextField jtf_deviceId;
    private javax.swing.JTextField jtf_password;
    private javax.swing.JTextField jtf_url;
    private javax.swing.JTextField jtf_username;
    // End of variables declaration//GEN-END:variables
}
